package se.webbzon.oschi01.utils;

import java.util.Observable;

public class Progress<T> extends Observable {
	
	private enum STATE {RUNNING, ABORTED, COMPLETED};
	
	private STATE state = STATE.RUNNING;
	
	private T result;
	
	private Exception e;
	
	private String text = "";
	
	private int progress = 0;
	
	public int getProgress() {
		return progress;
	}
	
	public T getResult() {
		return result;
	}
	
	public Exception getException() {
		return e;
	}
	
	public String getText() {
		return text;
	}
	
	public boolean isComplete() {
		return state == STATE.COMPLETED;
	}
	
	public boolean isAborted() {
		return state == STATE.ABORTED;
	}
	
	public boolean isRunning() {
		return state == STATE.RUNNING;
	}
	
	public void complete(T result, String text) {
		if (state == STATE.RUNNING) {
			this.result = result;
			state = STATE.COMPLETED;
			this.text = text == null ? "" : text;
			setChanged();
			notifyObservers(new ProgressEvent(this,ProgressEvent.Action.COMPLETED,result));
		}
	}
	
	public void complete(T result) {
		complete(result,null);
	}
	
	public void abort(Exception e) {
		abort(e,e.getMessage());
	}
	
	public void abort(Exception e, String text) {
		if (state == STATE.RUNNING) {
			state = STATE.ABORTED;
			this.text = text == null ? "" : text;
			this.e = e;
			setChanged();
			notifyObservers(new ProgressEvent(this,ProgressEvent.Action.ABORTED,e));
		}
	}
	
	public void setProgress(int progress, String text) {
		progress = Math.min(100, Math.max(0, progress));
		if (progress > this.progress) {
			this.progress = progress;
			this.text = text == null ? "" : text;
			setChanged();
			notifyObservers(new ProgressEvent(this,ProgressEvent.Action.INCREASED,progress));
		} else if (progress < this.progress) {
			this.progress = progress;
			this.text = text == null ? "" : text;
			setChanged();
			notifyObservers(new ProgressEvent(this,ProgressEvent.Action.DECREASED,progress));
		} else if (!getText().equals(text)) {
			setText(text);
		}
	}
	
	public void setProgress(int progress) {
		setProgress(progress,getText());
	}
	
	public void setText(String text) {
		this.text = text == null ? "" : text;
		setChanged();
		notifyObservers(new ProgressEvent(this,ProgressEvent.Action.CHANGED,this.text));
	}

}
